﻿/**
 *
 * @file ConditionQueue.h
 * @author Song
 * @date 2011-09-23
 */

#pragma once

#include <queue>

namespace helpers {

	/// addtogroup helpers
	/// @{

	/// 带有条件变量的队列
	/// 线程安全
	template <typename T>
	class ConditionQueue
	{
	public:
		typedef T	Value;
	
	public:
		ConditionQueue()
			: _mutex()
			, _cond()
			, _values()
			, _reset(false)
		{

		}
	public:
		/// 在队列尾部添加数据
		void push(const Value& v)
		{
			{
				boost::mutex::scoped_lock lock(_mutex);
				_values.push(v);
			}
			_cond.notify_one();
		}

		/// 取出队列头部数据
		/// 相当于 先调用front() 然后调用pop() ，但是只加了一次锁。
		Value get()
		{
			boost::mutex::scoped_lock lock(_mutex);
			while (_values.empty()) {
				_cond.wait(lock);
			}

			if (_reset) {
				_reset = false;
				return Value();
			}
			
			Value v = _values.front();
			_values.pop();
			return v;
		}

		void reset()
		{
			_reset = true;
			_cond.notify_one();
		}


	private:
		/// 返回队列头部数据引用
		Value& front() 
		{
			boost::mutex::scoped_lock lock(_mutex);
			while (_values.empty()) {
				_cond.wait(lock);
			}

			if (_reset) {
				_reset = false;
				return Value();
			}

			return _values.front();
		}
		
		/// 删除队列第一个数据
		void pop()
		{
			boost::mutex::scoped_lock lock(_mutex);
			if (!_values.empty()) {
				_values.pop();
			}
		}

	private:
		boost::mutex _mutex;
		boost::condition_variable _cond;
		std::queue<Value> _values;
		bool _reset;
	};


	struct PointerValue 
	{
	public:
		PointerValue()
			: content(NULL)
			, size(0)
		{

		}
		PointerValue(void* c, size_t len)
			: content(c)
			, size(len)
		{

		}
		void*   content;
		size_t  size;
	};
	
	class PointerQueue: public ConditionQueue<PointerValue>
	{
	public:
		void put(void* buf, size_t size)
		{
			this->push(PointerValue(buf, size));
		}
	};
}